(ns clj-tcp-server.tcp.tcp
  "作用如下:
   1. 启动指定端口的tcp server,基于aleph
   2. server stream上挂写入文件的函数
   3. 每个client的tcp包内容都写到同一个文件中"
  (:require
   [aleph.tcp :refer [start-server]]
   [byte-streams :as bs]
   [clojure.java.io :as io]
   [clojure.tools.logging :as log :refer [infof info]]
   [java-time :as jt]
   [manifold.deferred :as d]
   [manifold.stream :as s])
  (:import
   (java.io Closeable)))

(defn byte-array-to-file
  "byte-array 写入指定的outputstream"
  [out byte-array]
  (infof "有数据进入:%s" byte-array)
  (io/copy byte-array out)
  (.flush out)
  )

(defn stream-handler
  "注册函数`f`到某个`stream`"
  [f stream]
  (d/loop []
    (d/chain (s/take! stream ::drained)
             (fn [msg]
               (if (identical? ::drained msg)
                 ::drained
                 (f msg)))
             (fn [result]
               (when-not (identical? ::drained result)
                 (d/recur))))))

(defn request-dispatcher [s]
  (let [time         (jt/format "YY-MM-dd-hh-mm-ss-SSS" (jt/local-date-time))
        file-name    (format "data/%s.bin" time)
        out          (io/output-stream file-name)]
    (stream-handler
     (partial byte-array-to-file out)
     s
     )))

(defn register-tcp-server [port]
  (let [tcp-server (start-server
                    (fn [s info]
                      (infof "远端主机信息:%s" info)
                      (request-dispatcher s))
                    {:port port})]
    tcp-server))

(defn stop-tcp-server [server]
  (.close ^java.io.Closeable server))

(comment
  (def s (register-tcp-server 8888))
  (.close s)

  )
